{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Property函数: 定义属性"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 原生方法"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pangyazhou\n",
      "lixiaolong\n",
      "xxx\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "\n",
    "    # 访问name属性\n",
    "    def getname(self):\n",
    "        return self.name\n",
    "\n",
    "    # 设置name属性\n",
    "    def setname(self, name):\n",
    "        self.name = name\n",
    "\n",
    "    # 删除name属性\n",
    "    def delname(self):\n",
    "        self.name = 'xxx'\n",
    "\n",
    "person = Person('pangyazhou')\n",
    "print(person.getname())\n",
    "person.setname('lixiaolong')\n",
    "print(person.getname())\n",
    "person.delname()\n",
    "print(person.getname())"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## property() 函数\n",
    "Python 中提供了 property() 函数，可以实现在不破坏类封装原则的前提下，让开发者依旧使用“类对象.属性”的方式操作类中的属性。\n",
    "property() 函数的基本使用格式如下:\n",
    "> 属性名=property(fget=None, fset=None, fdel=None, doc=None)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "指明出处\n",
      "pangyazhou\n",
      "lixiaolong\n",
      "xxx\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self, name):\n",
    "        self.__name = name\n",
    "\n",
    "    # 访问name属性\n",
    "    def getname(self):\n",
    "        return self.__name\n",
    "\n",
    "    # 设置name属性\n",
    "    def setname(self, name):\n",
    "        self.__name = name\n",
    "\n",
    "    # 删除name属性\n",
    "    def delname(self):\n",
    "        self.__name = 'xxx'\n",
    "\n",
    "    # 为属性配置配置property函数\n",
    "    name = property(getname, setname, delname, '指明出处')\n",
    "\n",
    "print(Person.name.__doc__)\n",
    "# help(Person.name)\n",
    "person = Person('pangyazhou')\n",
    "print(person.name)\n",
    "person.name = 'lixiaolong'\n",
    "print(person.name)\n",
    "del person.name\n",
    "print(person.name)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "自定义 property 函数\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "outputs": [],
   "source": [
    "class MyProperty(object):\n",
    "\n",
    "    \"\"\"初始化方法\"\"\"\n",
    "    def __init__(self, fget=None, fset=None, fdel=None, doc=None):\n",
    "        print(fget, fset, fdel, doc)\n",
    "        self.fget = fget\n",
    "        self.fset = fset\n",
    "        self.fdel = fdel\n",
    "        self.__doc__ = doc\n",
    "\n",
    "    \"\"\"属性访问\"\"\"\n",
    "    def __get__(self, instance, owner):\n",
    "        if  instance is None:\n",
    "            return self.fget\n",
    "        if self.fget is None:\n",
    "            raise AttributeError(\"unreachable attribute\")\n",
    "        return self.fget(instance)\n",
    "\n",
    "    \"\"\"属性修改\"\"\"\n",
    "    def __set__(self, instance, value):\n",
    "        if self.fset is None:\n",
    "            raise AttributeError(\"can't set attribute\")\n",
    "        return self.fset(instance, value)\n",
    "\n",
    "    \"\"\"属性删除\"\"\"\n",
    "    def __delete__(self, instance):\n",
    "        if self.fdel is None:\n",
    "            raise AttributeError(\"can't delete attribute\")\n",
    "        return self.fdel(instance)\n",
    "\n",
    "    def getter(self, fget):\n",
    "        return type(self)(fget, self.fset, self.fdel, self.__doc__)\n",
    "\n",
    "    def setter(self, fset):\n",
    "        return type(self)(self.fget, fset, self.fdel, self.__doc__)\n",
    "\n",
    "    def deleter(self, fdel):\n",
    "        return type(self)(self.fget, self.fset, fdel, self.__doc__)\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<function Person.getname at 0x000001F44E471FC0> <function Person.setname at 0x000001F44E471480> <function Person.delname at 0x000001F44E471E10> 指明出处xxx\n",
      "指明出处xxx\n",
      "['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']\n",
      "指明出处xxx\n",
      "pangyazhou\n",
      "指明出处xxx\n",
      "lixiaolong\n",
      "指明出处xxx\n",
      "xxx\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self, name):\n",
    "        self.__name = name\n",
    "\n",
    "    # 访问name属性\n",
    "    def getname(self):\n",
    "        return self.__name\n",
    "\n",
    "    # 设置name属性\n",
    "    def setname(self, name):\n",
    "        self.__name = name\n",
    "\n",
    "    # 删除name属性\n",
    "    def delname(self):\n",
    "        self.__name = 'xxx'\n",
    "\n",
    "    # 为属性配置配置property函数\n",
    "    name = MyProperty(getname, setname, delname, '指明出处xxx')\n",
    "\n",
    "person = Person('pangyazhou')\n",
    "print(person.name)\n",
    "person.name = 'lixiaolong'\n",
    "print(person.name)\n",
    "del person.name\n",
    "print(person.name)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "data": {
      "text/plain": "17.44940226888645"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1.1**30"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}